#ifndef HTTP_HEADER_H
#define HTTP_HEADER_H

namespace fx {

    FX_DECLARE_CLASS(HttpHeader);

    class HttpHeader
        : public boost::noncopyable
    {
    public:
        typedef std::pair<std::string, std::string> KeyValuePair;
        typedef boost::unordered_multimap<std::string, std::string> MultiMap;
        typedef std::pair<MultiMap::const_iterator, MultiMap::const_iterator> MultiMapRange;
    public:
        virtual ~HttpHeader();
    public:
        static HttpHeaderPtr Create();
        static HttpHeaderPtr Create(const std::string& str_buf);
        static HttpHeaderPtr Create(std::istream& iss);

        bool Parse(const std::string& str_buf);
        bool Parse(std::istream& iss);

        std::string ToString() const;

        boost::uint32_t CountHeader(const std::string& key) const;
        boost::uint32_t CountHeader(const std::string& key, const std::string& value) const;

        std::string GetHeader(const std::string& key) const;
        std::vector<std::string> GetHeaders(const std::string& key) const;

        template <typename TargetType>
        bool GetHeaderAs(const std::string& key, TargetType& value)
        {
            if (CountHeader(key) == 0) {
                return false;
            }
            std::string value_str = GetHeader(key);
            try {
                value = boost::lexical_cast<TargetType>(value_str);
            }
            catch (const boost::bad_lexical_cast& ) {
                return false;
            }
            return true;
        }

        void AddHeader(const std::string& key, const std::string& value);
        void SetHeader(const std::string& key, const std::string& value);

        boost::uint32_t RemoveHeaders(const std::string&key);
        boost::uint32_t RemoveHeader(const std::string& key, const std::string& value);

        const std::string& FirstLine() const;
        void FirstLine(const std::string& line);

        std::string HeadersBuffer() const;

    protected:
        HttpHeader();

        static bool ParseKeyValue(const std::string& buffer, const std::string& delim, KeyValuePair& kv_pair);

        virtual bool ParseFirstLine();
        virtual void UpdateFirstLine();

    protected:
        std::string first_line_;
        MultiMap headers_;
        mutable std::string headers_buffer_;

    };

}

#endif//HTTP_HEADER_H
